using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using ShouldIt.Core;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ShouldIt.MSTest
{
    [Export(typeof(IAssertProvider))]
    public class AssertProvider : IAssertProvider
    {
        public void AreEqual(object expected, object actual)
        {
            Assert.AreEqual(expected, actual);
        }

        public void AreNotEqual(object expected, object actual)
        {
            Assert.AreNotEqual(expected, actual);
        }

        public void IsNotNull(object obj)
        {
            Assert.IsNotNull(obj);
        }

        public void IsNull(object value)
        {
            Assert.IsNull(value);
        }

        public void IsFalse(bool value)
        {
            Assert.IsFalse(value);
        }

        public void IsTrue(bool value)
        {
            Assert.IsTrue(value);
        }

        public void Fail(string messageFormat, params object[] args)
        {
            Assert.Fail(messageFormat, args);
        }

        public void Contains<T>(T item, IEnumerable<T> enumerable)
        {
            AssertIsICollection(enumerable);
            CollectionAssert.Contains(enumerable as ICollection, item);
        }

        public void NotContains<T>(T item, IEnumerable<T> enumerable)
        {
            AssertIsICollection(enumerable);
            CollectionAssert.DoesNotContain(enumerable as ICollection, item);
        }

        private void AssertIsICollection<T>(IEnumerable<T> enumerable)
        {
            Assert.IsInstanceOfType(enumerable, typeof(ICollection),
                "parameter 'enumerable' must implement ICollection");
        }

        public void Greater(int left, int right)
        {
            Assert.IsTrue(left > right, "'{0}' is not greater than '{1}'", left, right);
        }

        public void GreaterOrEqual(int left, int right)
        {
            Assert.IsTrue(left >= right, "'{0}' is not greater than or equal to '{1}'", left, right);
        }

        public void AreSame(object expected, object actual)
        {
            Assert.AreSame(expected, actual);
        }

        public void AreNotSame(object expected, object actual)
        {
            Assert.AreNotSame(expected, actual);
        }

        public void IsSubstringOf(string actual, string expectedSubstring)
        {
            StringAssert.Contains(actual, expectedSubstring);
        }

        public void IsInstanceOfType(object actual, Type expectedType)
        {
            Assert.IsInstanceOfType(actual, expectedType);
        }

        public void IsNotInstanceOfType(object actual, Type expectedType)
        {
            Assert.IsNotInstanceOfType(actual, expectedType);
        }
    }
}
